package com.xh.bussiness.jingyou.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.jingyou.constants.JingYouConstants;
import com.xh.bussiness.jingyou.service.IJYAuthService;
import com.xh.bussiness.jingyou.service.IJYQuestionService;
import com.xh.bussiness.jingyou.utils.Utility;
import com.xh.bussiness.tiku.bean.dto.QuestionDto;
import com.xh.bussiness.tiku.model.Knowledge;
import com.xh.bussiness.tiku.model.Question;
import com.xh.bussiness.tiku.bean.dto.QuestionSourceDto;
import com.xh.bussiness.tiku.model.QuestionType;
import com.xh.bussiness.tiku.service.IKnowledgeService;
import com.xh.bussiness.tiku.service.IQuestionTypeRelationService;
import com.xh.core.bean.XhPage;
import com.xh.core.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务类
 * </p>
 *
 * @author JQM
 * @since 2019-11-11
 */
@Service
public class JYQuestionServiceImpl implements IJYQuestionService{
	
	@Autowired
	private IJYAuthService authService; 
	@Autowired
	private IKnowledgeService knowledgeService;
	@Autowired
	private IQuestionTypeRelationService questionTypeRelationService;

	/**
	 * 查询菁优网的所有题目来源
	 * @param subject 学科
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<QuestionSourceDto> queryQuestionSource(String subject) throws Exception{
		String url = JingYouConstants.URL_ROOT_PATH + subject + "/common?tp=2";
		String result = Utility.sendGet(authService.getToken(), url);
		JSONArray array = JSON.parseArray(result);
		System.out.println(array);
		List<QuestionSourceDto> sources = new ArrayList<QuestionSourceDto>();
		for(int i=0;i<array.size();i++){
			JSONObject json = array.getJSONObject(i);
				Integer id = json.getInteger("Key");
				String name = json.getString("Value");
				QuestionSourceDto source = new QuestionSourceDto(id, name);
				sources.add(source);
		}
		return sources;
	}
	/**
	 * 查询菁优网的所有题型
	 * @param subject 学科
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<QuestionType> queryQuestionType(String subject) throws Exception{
		String url = JingYouConstants.URL_ROOT_PATH + subject + "/common?tp=1";
		String token = authService.getToken();
		System.out.println("token*******" + token);
		String result = Utility.sendGet(token, url);
		JSONArray array = JSON.parseArray(result);
		System.out.println(array);
		List<QuestionType> types = new ArrayList<QuestionType>();
		for(int i=0;i<array.size();i++){
			JSONObject json = array.getJSONObject(i);
				Integer id = json.getInteger("Key");
				String name = json.getString("Value");
				QuestionType type = new QuestionType(id, name);
				types.add(type);
		}
		return types;
	}
	/**
	 * 根据图片搜索试题
	 * @param imgPath
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<QuestionDto> queryByImg(String imgPath) throws Exception{
		String fileName = imgPath.substring(imgPath.lastIndexOf("/")+1);
		Map<String, String> files = new HashMap<String, String>();
		files.put(fileName, imgPath);
		String url = JingYouConstants.URL_ROOT_PATH+ "ques";
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_BY_IMG, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_BY_IMG);
		System.out.println("-------"+url+"---------"+imgPath);
		String result = Utility.sendForm(token, url, null, files);

		System.out.println(result);
		JSONObject json = JSON.parseObject(result);
		JSONArray array = json.getJSONArray("List");
		List<QuestionDto> questions = new ArrayList<QuestionDto>();
		for(int i=0;i<array.size();i++){
			questions.add(jyQues2QuestionDto(array.getJSONObject(i)));
		}
		System.out.println("queryByImg result:" + JSON.toJSONString(questions));
		return questions;
	}
	
	/// <summary>
		/// 按章节或考点获取试题列表
		/// </summary>
		/// <param name="subject">学科</param>
		/// <param name="tp">类别（1：教材；2：考点）</param>
		/// <param name="p1">教材标识或一级考点编号</param>
		/// <param name="p2">教材目录或二级考点编号</param>
		/// <param name="p3">考点编号（多个以逗号分隔）</param>
		/// <param name="cate">题型（参考获取试题题型API，“0”不限题型，多个以逗号分隔）</param>
		/// <param
		/// name="degree">难度（0：不限；11：易（0.8到1.0）；12：较易（0.6到0.8）；13：中档（0.4到0.6）；14：较难：（0.2到0.4）；15：难：（0.0到0.2））</param>
		/// <param name="sc">真题集（True：真题；False：不限）</param>
		/// <param name="gc">好题集（True：好题；False：不限）</param>
		/// <param name="rc">常考题（True：常考题；False：不限）</param>
		/// <param name="yc">压轴题（True：压轴题；False：不限）</param>
		/// <param name="ec">易错题（True：易错题；False：不限）</param>
		/// <param name="er">用户错题（True：错题；False：不限）</param>
		/// <param name="region">地区（参考获取地区API，“空”不限地区）</param>
		/// <param name="source">来源（参考获取试题来源API，“0”不限来源，多个以逗号分隔）</param>
		/// <param name="year">年份（“0”不限年份，多个以逗号分隔）</param>
		/// <param name="po">排序（0：综合排序；1：组卷次数；2：真题次数；3：试题难度）</param>
		/// <param name="pd">升降（0：升序；1：降序）</param>
		/// <param name="pi">页码</param>
		/// <param name="ps">每页记录数</param>
		/// <param name="onlyNos">（默认0）
		/// 假设：试题主考点为m，试题考点为集合A，查询考点为集合B；
		/// 0：m∈B；
		/// 1：m∈B 且A⊆B；
		/// 2：B⊆A
		/// </param>
		/// <returns>试题列表</returns>
	@Override
	public XhPage<QuestionDto> queryByParam(String subject, int tp, String p1, String p2, List<String> ids, String cate,
			int degree, Integer category, String region, String source, String year, int po, int pd,  int onlyNos, XhPage<QuestionDto> page) throws Exception {
		// 验证登录凭证
		category = category==null ? 0 : category; 
		Boolean sc = 1 == category, gc = 2==category, rc = 3==category, yc = 4==category, ec = 5==category, er = 6==category;
		String p3 = "";
		if (tp == 2) {
			Map<String, String> map = getKnowledgeIds(ids);
			p1 = map.get("first");
			p2 = map.get("second");
			p3 = map.get("three");
		} else {
			//章节考点编号
			if (!CollectionUtils.isEmpty(ids)) {
				p3 = ids.get(0);
			}
		}
		String url = String.format(
				"http://api.jyeoo.com/v1/%s/ques?tp=%s&p1=%s&p2=%s&p3=%s&ct=%s&dg=%s&sc=%s&gc=%s&rc=%s&yc=%s&ec=%s&er=%s&rg=%s&so=%s&yr=%s&po=%s&pd=%s&pi=%s&ps=%s&onlyNos=%s",
				subject, tp, URLEncoder.encode(p1, "UTF-8"), URLEncoder.encode(p2, "UTF-8"),
				URLEncoder.encode(p3, "UTF-8"), cate, degree, sc, gc, rc, yc, ec, er, region, source, year, po, pd, page.getCurrent(),
				page.getSize(), onlyNos);
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_BY_PAGE, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_BY_PAGE);
		String result = Utility.sendGet(token, url);
		str2Xhpage(page,result);
		System.out.println("**********" + result);
		return page;
	}
	/**
	 * 根据教材或考点查题
	 * @param subject
	 * @param searchType 查询方式（1：教材；2：考点）；
	 * @param points
	 * @param difficult
	 * @return
	 * @throws Exception 
	 */
	@Override
	public XhPage<QuestionDto> queryByKey(String subject, String key, XhPage<QuestionDto> page) throws Exception{
		String url;
		if (StringUtils.isEmpty(subject)) {
			// 混合学科搜索
			url = String.format(JingYouConstants.URL_ROOT_PATH + "ques?q=%s&t=%s&pi=%s&ps=%s", URLEncoder.encode(key, "UTF-8"),
					"", page.getCurrent(), page.getSize());
		} else {
			// 指定学科搜索
			url = String.format(JingYouConstants.URL_ROOT_PATH + "%s/ques?q=%s&t=%s&pi=%s&ps=%s", subject,
					URLEncoder.encode(key, "UTF-8"), "", page.getCurrent(), page.getSize());
		}
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_BY_KEY, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_BY_KEY);
		String result = Utility.sendGet(token, url);
		str2Xhpage(page,result);
		return page;
	}
	
	
	/**
	 * 查询题目解析
	 * @param subject 学科
	 * @param id 题目id，菁优网的题目id
	 * @return
	 * @throws Exception 
	 */
	@Override
	public QuestionDto queryAnalyze(String subject, String id) throws Exception{
		String url = String.format(JingYouConstants.URL_ROOT_PATH + subject + "/ques?id=%s",id);
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_ANALYSIS, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_ANALYSIS);
		String result =  Utility.sendGet(token, url);
		return jyQues2QuestionDto(JSON.parseObject(result));
	}
	/**
	 * 获取推荐题目
	 * @param subject 学科
	 * @param id 题目id，菁优网的题目id
	 * @param count 题目数量，小于等于20
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<QuestionDto> queryRecommond(String subject, String id, Integer count) throws Exception{
		count = count == null || count <= 0 ? 20 : count > 20 ? 20 : count;
		String url = String.format(JingYouConstants.URL_ROOT_PATH + "%s/ques/%s?ps=%s", subject, id, count);
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_RECOMMOND, JingYouConstants.INTERFACE_LIMIT_QUESTION_RECOMMOND);
		String result =  Utility.sendGet(token, url);
		List<QuestionDto> questions = new ArrayList<QuestionDto>();
		JSONArray array = JSON.parseArray(result);
		for(int i=0;i<array.size();i++){
			questions.add(jyQues2QuestionDto(array.getJSONObject(i)));
		}
		return questions;
	}
	
	/**
	 * 批量获取题目题干
	 * @param subject 学科
	 * @param ids 题目id集合
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<QuestionDto> queryTitles(String subject, List<String> ids) throws Exception{
		String url = String.format(JingYouConstants.URL_ROOT_PATH + subject + "/quesbatch?id=%s",URLEncoder.encode(JSON.toJSONString(ids), "UTF-8"));
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_TITLES, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_TITLES);
		String result =  Utility.sendGet(token, url);
		List<QuestionDto> questions = new ArrayList<QuestionDto>();
		JSONArray array = JSON.parseArray(result);
		for(int i=0;i<array.size();i++){
			questions.add(jyQues2QuestionDto(array.getJSONObject(i)));
		}
		return questions;
	}
	/**
	 * 批量获取题目题干
	 * @param subject 学科
	 * @param ids 题目id集合
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<Question> queryQuestions(String subject, List<String> ids) throws Exception{
		String url = String.format(JingYouConstants.URL_ROOT_PATH + subject + "/quesbatch?id=%s",URLEncoder.encode(JSON.toJSONString(ids), "UTF-8"));
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_QUERY_TITLES, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_TITLES);
		String result =  Utility.sendGet(token, url);
		List<Question> questions = new ArrayList<Question>();
		JSONArray array = JSON.parseArray(result);
		for(int i=0;i<array.size();i++){
			questions.add(jyQues2Question(array.getJSONObject(i)));
		}
		return questions;
	}
	public void str2Xhpage(XhPage<QuestionDto> page, String result){
		JSONObject json = JSON.parseObject(result);
		List<QuestionDto> questions = new ArrayList<QuestionDto>();
		JSONArray array = json.getJSONArray("Data");
		for(int i=0;i<array.size();i++){
			questions.add(jyQues2QuestionDto(array.getJSONObject(i)));
		}
		page.setRecords(questions);
		page.setTotal(json.getLongValue("Count"));
	}
	
	public QuestionDto jyQues2QuestionDto(JSONObject json){
		String id = json.getString("ID");
		String subject = getSubjectCode(json.getInteger("Subject"));
		// 题干
		String title = json.getString("Content");
		String analyse = json.getString("Analyse");
		String method = json.getString("Method");
		// 难度
		Float difficult = json.getFloatValue("Degree");
		// 题型
		Integer type = json.getInteger("Cate");
		// 来源
		String source = json.getString("Label");
		// 知识点
		JSONArray knownLedge = json.getJSONArray("Points");
		// 答案
		JSONArray answers = json.getJSONArray("Answers");
		
		// 选项
		JSONArray options = json.getJSONArray("Options");
		// 正确与否
		Integer viewCount = json.getInteger("ViewCount");
		
		String creator = json.getString("Teacher");
		
		QuestionDto quest = new QuestionDto();
		quest.setTitle(title);
		quest.setOption(changeOptions(options));
		quest.setRightAnswer(changeAnswer(type,answers));
		quest.setId(id);
		quest.setSubjectId(subject);
		quest.setDifficult(changeDifficult(difficult));
		quest.setSource(source);
		quest.setType(type);
		quest.setKnowledges(getPoints(subject, knownLedge));
		quest.setAnalysis(method);
		quest.setCreator(creator);
		quest.setRefId(id);
		quest.setCurrentVersion(1);
		Integer basicQuestionType = questionTypeRelationService.queryToolQuestionTypeByJyType(subject, type);
		if (basicQuestionType != null) {
			quest.setBasicQuestionType(basicQuestionType);
		}

		// 子题
		List<QuestionDto> children = new ArrayList<QuestionDto>();
		JSONArray child = json.getJSONArray("QuesChilds");
		for(int i=0;i<child.size();i++){
			children.add(jyQues2QuestionDto(child.getJSONObject(i)));
		}
		quest.setChilds(children);
		return quest;
	}

	@Override
	public byte[] downloadQuestion(String subject, String id, Integer method, Integer flag) throws Exception {
		String url = String.format(JingYouConstants.URL_ROOT_PATH + "%s/ques/%s?method=%s&flag=%s", subject, id, method,flag);
		String token = authService.getToken(JingYouConstants.INTERFACE_TYPE_QUESTION_DOWN, JingYouConstants.INTERFACE_LIMIT_QUESTION_QUERY_TITLES);
		return Utility.sendPut(token, url);
	}

	public Question jyQues2Question(JSONObject json){
		String id = json.getString("ID");
		String subject = getSubjectCode(json.getInteger("Subject"));
		// 题干
		String title = json.getString("Content");
		// 难度
		Float difficult = json.getFloatValue("Degree");
		// 题型
		Integer type = json.getInteger("Cate");
		// 来源
		String source = json.getString("Label");
		// 答案
		JSONArray answers = json.getJSONArray("Answers");
		
		// 选项
		JSONArray options = json.getJSONArray("Options");
		// 正确与否
		
		Question quest = new Question();
		quest.setTitle(title);
		quest.setOptionContent(changeOptions(options).toJSONString());
		quest.setRightAnswer(changeAnswer(type,answers).toJSONString());
		quest.setId(id);
		quest.setRefId(id);
		quest.setSubjectId(subject);
		quest.setDifficult(changeDifficult(difficult));
		quest.setSource(source);
		quest.setType(type);
		quest.setCurrentVersion(1);
		return quest;
	}
	
	// 难度（0：不限；11：易（0.8到1.0）；12：较易（0.6到0.8）；13：中档（0.4到0.6）；14：较难：（0.2到0.4）；15：难：（0.0到0.2））
	private Integer changeDifficult(Float difficult) {
		if (0.8 < difficult && difficult <= 1.0) {
			return 11;
		}
		if (0.6 < difficult && difficult <= 0.8) {
			return 12;
		}
		if (0.4 < difficult && difficult <= 0.6) {
			return 13;
		}
		if (0.2 < difficult && difficult <= 0.4) {
			return 14;
		}
		if (0.0 < difficult && difficult <= 0.2) {
			return 15;
		}
		return 0;
	}
	/**
	 * 选项转换
	 * @param arr
	 * @return
	 */
	private JSONArray changeOptions(JSONArray arr){
		JSONArray options = new JSONArray();
		if(arr.size()>0){
			for(int i=0;i<arr.size();i++){
				JSONObject option = new JSONObject();
				option.put("no", i+1);
				option.put("content", arr.getString(i));
				options.add(option);
			}
		}
		return options;
	}
	/**
	 * 答案转换
	 * @param type
	 * @param arr
	 * @return
	 */
	private JSONArray changeAnswer(Integer type, JSONArray arr){
		// 单选题
		if(type == 1){
			return arr;
		}
		// 填空题
		if(type == 2){
			JSONArray answers = new JSONArray();
			if(arr.size()>0){
				for(int i=0;i<arr.size();i++){
					JSONObject answer = new JSONObject();
					answer.put("no", i+1);
					answer.put("content", arr.getString(i));
					answers.add(answer);
				} 
			}
			return answers;
		}
		return null;
	}
	/**
	 * 获取知识点
	 * @param arr
	 * @return
	 */
	private List<Knowledge> getPoints(String subject, JSONArray arr){
		if(arr.isEmpty()){
			return null;
		}
		List<String> nos = new ArrayList<String>();
		List<String> names = new ArrayList<String>();
		for(int i=0;i<arr.size();i++){
			JSONObject json = arr.getJSONObject(i);
			String key = json.getString("Key");
			String name = json.getString("Value");
			nos.add(key);
			names.add(name);
		}
		QueryWrapper<Knowledge> qw = new QueryWrapper<Knowledge>();
		qw.eq("subject", subject);
		qw.in("no", nos);
		qw.in("name", names);
		return knowledgeService.queryByCondition(qw);
	}
	
	private Map<String, String> getKnowledgeIds(List<String> list){
		if(list==null || list.isEmpty()){
			return null;
		}
		String first = list.get(0);
		list.remove(0);
		String second = "";
		if(!list.isEmpty()){
			second = list.get(0);
			list.remove(0);
		}
		String three = "";
		if(!list.isEmpty()){
			three = list.toString().substring(1, list.toString().length()-1);
		}
		Map<String, String> map = new HashMap<String, String>(3);
		map.put("first", first);
		map.put("second", second);
		map.put("three", three);
		return map;
	}
	
	public String getSubjectCode(Integer subjectId){
		switch (subjectId) {
		case 10:
			return "math3";
		case 11:
			return "chinese3";
		case 12:
			return "english3";
		case 14:
			return "science3";
		case 20:
			return "math";
		case 21:
			return "physics";
		case 22:
			return "chemistry";
		case 23:
			return "bio";
		case 25:
			return "geography";
		case 26:
			return "chinese";
		case 27:
			return "english";
		case 28:
			return "politics";
		case 29:
			return "history";
		case 30:
			return "math2";
		case 31:
			return "physics2";
		case 32:
			return "chemistry2";
		case 33:
			return "bio2";
		case 35:
			return "geography2";
		case 37:
			return "english2";
		case 36:
			return "chinese2";
		case 38:
			return "politics2";
		case 39:
			return "history2";
		case 42:
			return "tech1";
		case 43:
			return "tech2";
			
		default:
			break;
		}
		return "";
	}
}
